package com.eshop.modules.product.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eshop.common.service.impl.BaseServiceImpl;
import com.eshop.common.utils.QueryHelpPlus;
import com.eshop.domain.BaseDomain;
import com.eshop.dozer.service.IGenerator;
import com.eshop.enums.ShopCommonEnum;
import com.eshop.modules.cart.vo.StoreCartQueryVo;
import com.eshop.modules.product.domain.StoreProductReply;
import com.eshop.modules.product.service.StoreProductReplyService;
import com.eshop.modules.product.service.StoreProductService;
import com.eshop.modules.product.service.dto.StoreProductReplyDto;
import com.eshop.modules.product.service.dto.StoreProductReplyQueryCriteria;
import com.eshop.modules.product.service.mapper.StoreProductReplyMapper;
import com.eshop.modules.product.vo.ReplyCountVo;
import com.eshop.modules.product.vo.StoreProductReplyQueryVo;
import com.eshop.modules.user.service.UserService;
import com.eshop.utils.FileUtil;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = { Exception.class })
public class StoreProductReplyServiceImpl extends BaseServiceImpl<StoreProductReplyMapper, StoreProductReply> implements StoreProductReplyService
{
    @Autowired
    private IGenerator generator;
    @Autowired
    private UserService userService;
    @Autowired
    private StoreProductService storeProductService;
    
    public ReplyCountVo getReplyCount(final long productId) {
        final int sumCount = this.productReplyCount(productId);
        if (sumCount == 0) {
            return new ReplyCountVo();
        }
        final int goodCount = (this.baseMapper).selectCount((Wrappers.<StoreProductReply>lambdaQuery().eq(StoreProductReply::getProductId, productId)).eq(StoreProductReply::getProductScore, 5));
        final int inCount = (this.baseMapper).selectCount(((Wrappers.<StoreProductReply>lambdaQuery().eq(StoreProductReply::getProductId, productId)).lt(StoreProductReply::getProductScore, 5)).gt(StoreProductReply::getProductScore, 2));
        final int poorCount = (this.baseMapper).selectCount((Wrappers.<StoreProductReply>lambdaQuery().eq(StoreProductReply::getProductId, productId)).le(StoreProductReply::getProductScore, 2));
        final String replyChance = "" + NumberUtil.round(NumberUtil.mul(NumberUtil.div((float)goodCount, (float)sumCount), 100.0f), 2);
        final String replyStar = "" + NumberUtil.round(NumberUtil.mul(NumberUtil.div((float)goodCount, (float)sumCount), 5.0f), 2);
        return ReplyCountVo.builder().sumCount(sumCount).goodCount(goodCount).inCount(inCount).poorCount(poorCount).replyChance(replyChance).replySstar(replyStar).build();
    }
    
    public StoreProductReplyQueryVo handleReply(final StoreProductReplyQueryVo replyQueryVo) {
        // 首先，从传入的 replyQueryVo 中获取并解析 cartInfo 字段，将其转化为 StoreCartQueryVo 类型的对象。
        // 如果这个购物车信息存在，且购物车中包含的产品信息及其属性信息也存在，
        // 那么就从属性信息中提取出 sku 并设置到 replyQueryVo 对象的 sku 属性上。
        final StoreCartQueryVo cartInfo = (StoreCartQueryVo)JSONObject.parseObject(replyQueryVo.getCartInfo(), (Class)StoreCartQueryVo.class);
        if (ObjectUtil.isNotNull(cartInfo) && ObjectUtil.isNotNull(cartInfo.getProductInfo()) && ObjectUtil.isNotNull(cartInfo.getProductInfo().getAttrInfo())) {
            replyQueryVo.setSku(cartInfo.getProductInfo().getAttrInfo().getSku());
        }
        /*
            计算平均评分：将产品评分 (replyQueryVo.getProductScore()) 和服务评分 (replyQueryVo.getServiceScore()) 相加后再除以2，
            得到一个平均星数。使用 NumberUtil 工具类进行数学计算，并将结果转换为 BigDecimal 类型。
            最后将平均星数转换为整数并设置到 replyQueryVo 的 star 字段。
         */
        BigDecimal star = NumberUtil.add((Number)replyQueryVo.getProductScore(), (Number)replyQueryVo.getServiceScore());
        star = NumberUtil.div((Number)star, (Number)2);
        replyQueryVo.setStar(String.valueOf(star.intValue()));
        if (StrUtil.isEmpty((CharSequence)replyQueryVo.getComment())) {
            replyQueryVo.setComment("此用户没有填写评价");
        }
        return replyQueryVo;
    }
    
    public StoreProductReplyQueryVo getReply(final long productId) {
        /*
           select A.product_score as productScore,A.service_score as serviceScore,A.comment,
           A.merchant_reply_content as merchantReplyContent,A.merchant_reply_time as merchantReplyTime,
           A.pics as pictures,A.create_Time as createTime,B.nickname,B.avatar,C.cart_info as cartInfo
           from store_product_reply A left join eshop_user B on A.uid = B.uid left
           join store_order_cart_info C on A.`unique` = C.`unique`
           where A.product_id=30 and A.is_del=0 order by A.create_Time DESC limit 1
         */
        final StoreProductReplyQueryVo vo = (this.baseMapper).getReply(productId);
        if (ObjectUtil.isNotNull(vo)) {
            return this.handleReply((this.baseMapper).getReply(productId));
        }
        return null;
    }

    @Override

    public List<StoreProductReplyQueryVo> getReplyList(final long productId, final int type, final int page, final int limit) {
        final List<StoreProductReplyQueryVo> newList = new ArrayList<StoreProductReplyQueryVo>();
        final Page<StoreProductReply> pageModel = (Page<StoreProductReply>)new Page(page, (long)limit);
        final List<StoreProductReplyQueryVo> list = (this.baseMapper).selectReplyList(pageModel, productId, type);
        final List<StoreProductReplyQueryVo> list2 = list.stream().map(i -> {
            StoreProductReplyQueryVo vo = new StoreProductReplyQueryVo();
            BeanUtils.copyProperties(i, vo);
            if (i.getPictures().contains(",")) {
                vo.setPics(i.getPictures().split(","));
            }
            return vo;
        }).collect(Collectors.toList());
        for (final StoreProductReplyQueryVo queryVo : list2) {
            newList.add(this.handleReply(queryVo));
        }
        return newList;
    }

    public int getInfoCount(final Integer oid, final String unique) {
        final LambdaQueryWrapper<StoreProductReply> wrapper = (LambdaQueryWrapper<StoreProductReply>)new LambdaQueryWrapper();
        (wrapper.eq(StoreProductReply::getUnique, unique)).eq(StoreProductReply::getOid, oid);
        return (this.baseMapper).selectCount(wrapper);
    }
    
    public int productReplyCount(final long productId) {
        return (this.baseMapper).selectCount(Wrappers.<StoreProductReply>lambdaQuery().eq(StoreProductReply::getProductId, productId));
    }
    
    public int replyCount(final String unique) {
        final LambdaQueryWrapper<StoreProductReply> wrapper = (LambdaQueryWrapper<StoreProductReply>)new LambdaQueryWrapper();
        wrapper.eq(StoreProductReply::getUnique, unique);
        return (this.baseMapper).selectCount(wrapper);
    }

    // 计算指定产品（由 productId 标识）获得的五星好评率（以百分比形式返回）
    public String replyPer(final long productId) {
        // 指定产品ID，未删除，产品评分为5星
        final LambdaQueryWrapper<StoreProductReply> wrapper = (LambdaQueryWrapper<StoreProductReply>)new LambdaQueryWrapper();
        ((wrapper.eq(StoreProductReply::getProductId, productId)).eq(BaseDomain::getIsDel, ShopCommonEnum.DELETE_0.getValue())).eq(StoreProductReply::getProductScore, 5);
        // 查出五星好评数量
        final int productScoreCount = (this.baseMapper).selectCount(wrapper);
        // 查出总评论数量
        final int count = this.productReplyCount(productId);
        // 如果总评论数大于0，则计算五星好评率（五星好评数量 / 总评论数 * 100%），
        // 使用 NumberUtil 类的 round 和 div 方法进行计算，保留两位小数，然后转换为字符串形式返回。
        if (count > 0) {
            return "" + NumberUtil.round(NumberUtil.mul(NumberUtil.div((float)productScoreCount,
                    (float)count), 100.0f), 2);
        }
        // 如果总评论数为0，则返回字符串 "0"，表示好评率为0%。
        return "0";
    }
    
    public Map<String, Object> queryAll(final StoreProductReplyQueryCriteria criteria, final Pageable pageable) {
        this.getPage(pageable);
        final PageInfo<StoreProductReply> page = (PageInfo<StoreProductReply>)new PageInfo((List)this.queryAll(criteria));
        final Map<String, Object> map = new LinkedHashMap<String, Object>(2);
        map.put("content", this.generator.convert(page.getList(), (Class)StoreProductReplyDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }
    
    public List<StoreProductReply> queryAll(final StoreProductReplyQueryCriteria criteria) {
        final List<StoreProductReply> storeProductReplyList = (this.baseMapper).selectList(QueryHelpPlus.getPredicate(StoreProductReply.class, criteria));
        storeProductReplyList.forEach(yxStoreProductReply -> {
            yxStoreProductReply.setUser(this.userService.getById(yxStoreProductReply.getUid()));
            yxStoreProductReply.setStoreProduct(this.storeProductService.getById(yxStoreProductReply.getProductId()));
            return;
        });
        return storeProductReplyList;
    }
    
    public void download(final List<StoreProductReplyDto> all, final HttpServletResponse response) throws IOException {
        final List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (final StoreProductReplyDto yxStoreProductReply : all) {
            final Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("用户ID", yxStoreProductReply.getUid());
            map.put("订单ID", yxStoreProductReply.getOid());
            map.put("唯一id", yxStoreProductReply.getUnique());
            map.put("产品id", yxStoreProductReply.getProductId());
            map.put("某种商品类型(普通商品、秒杀商品）", yxStoreProductReply.getReplyType());
            map.put("商品分数", yxStoreProductReply.getProductScore());
            map.put("服务分数", yxStoreProductReply.getServiceScore());
            map.put("评论内容", yxStoreProductReply.getComment());
            map.put("评论图片", yxStoreProductReply.getPics());
            map.put("管理员回复内容", yxStoreProductReply.getMerchantReplyContent());
            map.put("管理员回复时间", yxStoreProductReply.getMerchantReplyTime());
            map.put("0未回复1已回复", yxStoreProductReply.getIsReply());
            list.add(map);
        }
        FileUtil.downloadExcel((List)list, response);
    }
}
